﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Aribaccio;
using Aribaccio.Device;
using BDPAutodetect.Device;
using BDPAutodetect.Models;

namespace BDPAutodetect.Mgrcore
{
    /// <summary>
    /// Modbus检测设备基类
    /// </summary>
    public class DetectDeviceModbus : DetectDeviceBase
    {
        /// <summary>
        /// 指标设备协议数据集
        /// </summary>
        protected List<MTargetSlave> TargetSlaves { get; set; }
        /// <summary>
        /// 设备通讯辅助实例
        /// </summary>
        protected DeviceSerialModbus<IDevicePara>? DeviceItem { get; set; }
        /// <summary>
        /// 是否打开
        /// </summary>
        public override bool IsOpen => this.DeviceItem?.IsOpen ?? false;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="argName">名称</param>
        /// <param name="argDeviceType">设备类型</param>
        /// <param name="argStationType">工位类型</param>
        /// <param name="argDevice">设备连接</param>
        protected DetectDeviceModbus(string argName, DeviceType argDeviceType, DeviceStationType argStationType, DeviceSerialModbus<IDevicePara> argDevice, List<MTargetSlave> argTargetSlaves)
            : base(argName, argDeviceType, argStationType)
        {
            this.DeviceItem = argDevice;
            this.TargetSlaves = argTargetSlaves;
        }

        /// <summary>
        /// 写入设备数据
        /// </summary>
        /// <param name="argStationType">设备工位类型</param>
        /// <param name="argTargetType">设备指标类型</param>
        /// <param name="argInputData">协议数据</param>
        /// <returns></returns>
        public virtual bool WriteDeviceData<TInput>(DeviceStationType argStationType, DeviceTargetType argTargetType, TInput argInputData)
            where TInput : struct
        {
            //获取指标配置
            MTargetSlave? targetSlave = this.GetTargetSlave(argStationType, argTargetType);
            if (targetSlave == null) return false;

            ModbusSlaveData<TInput> NodeDataItem = new ModbusSlaveData<TInput>(targetSlave.CloneDeviceSlave(), argInputData);
            //写入设备
            return this.WriteDeviceData(NodeDataItem);
        }

        /// <summary>
        /// 读取设备数据
        /// </summary>
        /// <param name="argStationType">设备工位类型</param>
        /// <param name="argDeviceTarget">设备指标类型</param>
        /// <returns></returns>
        public virtual ResultModel<byte> ReadDeviceDataByte<TInput>(DeviceStationType argStationType, DeviceTargetType argTargetType, TInput argInputData)
              where TInput : struct
        {
            ResultModel<byte> resultData = new(ResultStatus.Failure);
            //获取指标配置
            MTargetSlave? targetSlave = this.GetTargetSlave(argStationType, argTargetType);
            if (targetSlave == null) return resultData;

            return this.ReadDeviceDataByte<TInput>(targetSlave, argInputData);
        }

        /// <summary>
        /// 读取设备数据
        /// </summary>
        /// <param name="argStationType">设备工位类型</param>
        /// <param name="argTargetType">设备指标类型</param>
        /// <returns></returns>
        public virtual ResultModel<decimal> ReadDeviceDataDecimal<TInput>(DeviceStationType argStationType, DeviceTargetType argTargetType, TInput argInputData)
            where TInput : struct
        {
            ResultModel<decimal> resultData = new(ResultStatus.Failure);
            //获取指标配置
            MTargetSlave? targetSlave = this.GetTargetSlave(argStationType, argTargetType);
            if (targetSlave == null) return resultData;

            return this.ReadDeviceDataDecimal<TInput>(targetSlave, argInputData);
        }

        /// <summary>
        /// 读取设备数据
        /// </summary>
        /// <typeparam name="TInput">传参结构数据模型</typeparam>
        /// <typeparam name="TOutput">输出结构数据模型</typeparam>
        /// <param name="argStationType">设备工位类型</param>
        /// <param name="argTargetType">设备指标类型</param>
        /// <param name="argInputData">输入数据</param>
        /// <returns></returns>
        public virtual ResultModel<TOutput> ReadDeviceData<TInput, TOutput>(DeviceStationType argStationType, DeviceTargetType argTargetType, TInput argInputData)
            where TInput : struct
            where TOutput : struct
        {
            ResultModel<TOutput> ResultData = new ResultModel<TOutput>(ResultStatus.Failure);
            //获取指标配置
            MTargetSlave? targetSlave = this.GetTargetSlave(argStationType, argTargetType);
            if (targetSlave == null) return ResultData;

            //读取数据
            return this.ReadDeviceData<TInput, TOutput>(targetSlave, argInputData);
        }


        /// <summary>
        /// 读取设备数据
        /// </summary>
        /// <param name="argTargetSlave">设备工位类型</param>
        /// <param name="argInputData">设备指标类型</param>
        /// <returns></returns>
        public virtual ResultModel<byte> ReadDeviceDataByte<TInput>(MTargetSlave argTargetSlave, TInput argInputData)
              where TInput : struct
        {
            ResultModel<byte> resultData = new(ResultStatus.Failure);
            if (argTargetSlave == null) return resultData;

            ModbusSlaveData<TInput> targetSlaveData = new ModbusSlaveData<TInput>(argTargetSlave.CloneDeviceSlave(), argInputData);
            //读取数据
            ResultModel<StructOutputByte> resultStruct = this.ReadDeviceData<TInput, StructOutputByte>(argTargetSlave, argInputData);
            //判断是否读取成功
            if (resultStruct.ResultState)
            {
                resultData.ResultCode = ResultStatus.Succeed;
                resultData.Data = resultStruct.Data.DataValue;
            }
            else
            {
                resultData.ResultCode = resultStruct.ResultCode;
                resultData.ResultMsg = !string.IsNullOrEmpty(resultStruct.ResultMsg) ? resultStruct.ResultMsg : "读取数据失败";
            }
            return resultData;
        }

        /// <summary>
        /// 读取设备数据
        /// </summary>
        /// <param name="argStationType">设备工位类型</param>
        /// <param name="argDeviceTarget">设备指标类型</param>
        /// <returns></returns>
        public virtual ResultModel<decimal> ReadDeviceDataDecimal<TInput>(MTargetSlave argTargetSlave, TInput argInputData)
              where TInput : struct
        {
            ResultModel<decimal> resultData = new(ResultStatus.Failure);
            if (argTargetSlave == null) return resultData;

            ResultModel<StructOutputShort> resultStruct = this.ReadDeviceData<TInput, StructOutputShort>(argTargetSlave, argInputData);
            if (resultStruct.ResultState)
            {
                resultData.ResultCode = ResultStatus.Succeed;
                resultData.Data = argTargetSlave.DataPrecision > 0
                    ? resultStruct.Data.DataValue * argTargetSlave.DataPrecision
                    : resultStruct.Data.DataValue;
            }
            else
            {
                resultData.ResultCode = resultStruct.ResultCode;
                resultData.ResultMsg = !string.IsNullOrEmpty(resultStruct.ResultMsg) ? resultStruct.ResultMsg : "读取数据失败";
            }
            return resultData;
        }

        /// <summary>
        /// 读取设备数据
        /// </summary>
        /// <typeparam name="TInput">传参结构数据模型</typeparam>
        /// <typeparam name="TOutput">输出结构数据模型</typeparam>
        /// <param name="argTargetSlave">设备协议</param>
        /// <param name="argInputData">输入数据</param>
        /// <returns></returns>
        public virtual ResultModel<TOutput> ReadDeviceData<TInput, TOutput>(MTargetSlave argTargetSlave, TInput argInputData)
            where TInput : struct
            where TOutput : struct
        {
            ResultModel<TOutput> ResultData = new ResultModel<TOutput>(ResultStatus.Failure);
            ModbusSlaveData<TInput> targetSlaveData = new ModbusSlaveData<TInput>(argTargetSlave.CloneDeviceSlave(), argInputData);
            //读取数据
            ResultModel<ModbusSlaveData<TOutput>> resultModel = this.ReadDeviceData<TInput, TOutput>(targetSlaveData);
            //判断是否读取成功
            if (resultModel.ResultState && resultModel.Data != null)
            {
                ResultData.ResultCode = ResultStatus.Succeed;
                ResultData.Data = resultModel.Data.SlaveData;
            }
            else
            {
                ResultData.ResultCode = !resultModel.ResultState ? resultModel.ResultCode : ResultStatus.Failure;
                ResultData.ResultMsg = !resultModel.ResultState ? resultModel.ResultMsg : "读取数据失败";
            }
            return ResultData;
        }


        /// <summary>
        /// 写入设备数据
        /// </summary>
        /// <typeparam name="TInput">传参结构数据模型</typeparam>
        /// <param name="argSlaveData">配置协议数据</param>
        /// <returns></returns>
        protected virtual bool WriteDeviceData<TInput>(ModbusSlaveData<TInput> argSlaveData) where TInput : struct
        {
            bool bResult = false;
            if (this.DeviceItem == null || !this.DeviceItem.IsOpen) return bResult;
            try
            {
                Result result = this.DeviceItem.WriteModbusData(argSlaveData);
                if (result.ResultState) bResult = true;
            }
            catch (Exception)
            {
                return bResult = false;
            }
            return bResult;
        }

        /// <summary>
        /// 读取串行设备数据
        /// </summary>
        /// <typeparam name="TInput">传参结构数据模型</typeparam>
        /// <typeparam name="TOutput">输出结构数据模型</typeparam>
        /// <param name="argSlaveData">配置协议数据</param>
        /// <returns></returns>
        protected virtual ResultModel<ModbusSlaveData<TOutput>> ReadDeviceData<TInput, TOutput>(ModbusSlaveData<TInput> argSlaveData)
            where TInput : struct
            where TOutput : struct
        {
            //定义返回数据
            ResultModel<ModbusSlaveData<TOutput>> ResultData = new ResultModel<ModbusSlaveData<TOutput>>(ResultStatus.Failure, new ModbusSlaveData<TOutput>((ModbusSlave)argSlaveData));
            if (this.DeviceItem == null || !this.DeviceItem.IsOpen) return ResultData;
            try
            {
                ResultData = this.DeviceItem.ReadModbusModelData<TInput, TOutput>(argSlaveData);
            }
            catch (Exception ep)
            {
                ResultData.ResultCode = ResultStatus.Exception;
                ResultData.ResultMsg = "[读取][发送Modubs读取]，异常：" + ep.Message;
            }
            return ResultData;
        }

        /// <summary>
        /// 获取设备指标协议
        /// </summary>
        /// <param name="argStationType">设备工位类型</param>
        /// <param name="argTargetType">设备指标类型</param>
        /// <returns></returns>
        protected virtual MTargetSlave? GetTargetSlave(DeviceStationType argStationType, DeviceTargetType argTargetType)
        {
            if (this.TargetSlaves == null || TargetSlaves.Count <= 0) return null;
            return this.TargetSlaves.FirstOrDefault(v => v.Station.StationType == argStationType && v.Target.TargetType == argTargetType);
        }
    }
}
